import logging
import traceback

from django.http import Http404
from rest_framework.exceptions import AuthenticationFailed, APIException, PermissionDenied, ValidationError, \
    MethodNotAllowed, Throttled, NotAuthenticated
from rest_framework.views import exception_handler, set_rollback

from utils.MyResponse import ErrorResponse

logger = logging.getLogger(__name__)


def CustomExceptionHandler(ex, context):
    """
    统一异常拦截处理
    :param ex:
    :param context:
    :return:
    """
    # print(type(ex))
    msg = ""
    code = 400
    # 调用默认的异常处理函数
    response = exception_handler(ex, context)
    # print(type(ex), ex)
    # print(response)
    # print(response.data)
    if isinstance(ex, AuthenticationFailed) or isinstance(ex, NotAuthenticated):
        # 如果是身份验证错误
        msg = '身份验证失败'
        code = 401
        if response.data.get('detail').code == 'no_active_account':
            code = 400
            msg = '账号或密码错误'

    elif isinstance(ex, Http404):
        code = 400
        msg = "接口地址不正确"
    elif isinstance(ex, ValidationError):
        # msg = str(ex)
        msg = '请提交正确字段'
        code = 400
        if isinstance(response.data, dict):
            if response.data.get('username'):
                if response.data.get('username')[0].code == 'unique':
                    msg = '用户已存在'
            else:
                keys = list(response.data.keys())
                s = ','.join(keys)
                msg = '请提交正确' + s
        elif isinstance(response.data, list):
            msg = response.data[0]

    elif isinstance(ex, MethodNotAllowed):
        # msg = str(ex)
        msg = '没有该请求方法'
        code = 400
    elif isinstance(ex, Throttled):
        msg = '请求太快了，请稍后再试'
        code = 400
    elif isinstance(ex, APIException):
        set_rollback()
        # msg = ex.detail
        if isinstance(ex, PermissionDenied):
            msg = f'您没有权限'
            # msg = f'您没有权限 ({context["request"].method}: {context["request"].path})'
        else:
            msg = '错误'
            # 手动抛异常时
            if response.data.get('detail').code == 'manually':
                msg = response.data.get('detail')
            else:
                logger.exception(traceback.format_exc())
    else:
        logger.exception(traceback.format_exc())
        msg = '错误'
        code = 400
    return ErrorResponse(msg=msg, code=code)
